package com.snailhd.framework.common.entity;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Map;

/**
 * @author hd
 * @date 2020-01-04 16:19
 */

@Setter
@Getter
@Accessors(chain = true)
@NoArgsConstructor
@ToString
public class IResult<T> implements Serializable {

    private String code;

    private String msg;

    private String subCode;

    private String subMsg;

    private transient Map<String,Object> subArgs;

    private T data;

    public boolean isSuccess(){
        return ResultCodeEnums.SUCCESS.name().equals(code);
    }
    public boolean isFail(){
        return !ResultCodeEnums.SUCCESS.name().equals(code);
    }

    public IResult(ResultCode code, SubCode sub, Map<String,Object> subArgs, T data) {
        this.code = code.getCode();
        this.msg = code.getMsg();
        this.subCode = sub.getCode();
        this.subMsg = sub.getMsg();
        this.subArgs = subArgs;
        this.data = data;
    }

    public static <T> IResult<T> ofSuccess() {
        return new IResult<T>( ResultCodeEnums.SUCCESS,null,null,null);
    }

    public static <T> IResult<T> ofSuccess(T data) {

        return new IResult<T>( ResultCodeEnums.SUCCESS,null,null,data);
    }

    public IResult<T> genSuccess(){
        this.code = ResultCodeEnums.SUCCESS.name();
        this.subCode = null;
        this.subArgs = null;
        this.data = null;
        return this;
    }

    public IResult<T> genSuccess(T data){
        this.code = ResultCodeEnums.SUCCESS.name();
        this.subCode = null;
        this.subArgs = null;
        this.data = data;
        return this;
    }


    public static <T> IResult<T> ofFail(SubCode subCode) {
        return new IResult<T>( ResultCodeEnums.FAIL,subCode,null,null);
    }

    public static <T> IResult<T> ofFail(SubCode subCode,Map<String,Object> subArgs) {
        return new IResult<T>( ResultCodeEnums.FAIL,subCode,subArgs,null);
    }


    public IResult<T> genFail(SubCode sub){
        this.code = ResultCodeEnums.FAIL.getCode();
        this.msg = ResultCodeEnums.FAIL.getMsg();
        this.subCode = sub.getCode();
        this.subMsg = sub.getMsg();
        this.subArgs = null;
        this.data = null;
        return this;
    }

    public IResult<T> genFail(SubCode sub,Map<String,Object> subArgs){
        this.code = ResultCodeEnums.FAIL.getCode();
        this.msg = ResultCodeEnums.FAIL.getMsg();
        this.subCode = sub.getCode();
        this.subMsg = sub.getMsg();
        this.subArgs = subArgs;
        this.data = null;
        return this;
    }

    public static <T,N> IResult<T> ofNotData(IResult<N> input){
        IResult<T> iResult = new IResult<>();
        iResult.setCode(input.getCode());
        iResult.setMsg(input.getMsg());
        iResult.setSubCode(input.getSubCode());
        iResult.setSubMsg(input.getSubMsg());
        iResult.setSubArgs(input.getSubArgs());
        return iResult;
    }

    public static <T> IResult<T> ofSuccessOrElse(boolean success,SubCode sub){
        if(success){
            return IResult.ofSuccess();
        }
        return IResult.ofFail(sub);
    }

    public static <T> IResult<T> ofSuccessOrElse(boolean success,SubCode sub,Map<String,Object> args){
        if(success){
            return IResult.ofSuccess();
        }
        return IResult.ofFail(sub,args);
    }

    public static <T> IResult<T> ofDataSuccessOrElse(T data,SubCode sub){
        if(data!=null){
            return IResult.ofSuccess(data);
        }
        return IResult.ofFail(sub);
    }

    public static <T> IResult<T> ofDataSuccessOrElse(T data,SubCode sub,Map<String,Object> args){
        if(data!=null){
            return IResult.ofSuccess(data);
        }
        return IResult.ofFail(sub,args);
    }

}
